package cn.edu.nuaa.aadl2.generatorC.template

import static extension cn.edu.nuaa.aadl2.generatorC.utils.Tools.*
import static extension cn.edu.nuaa.aadl2.generatorC.utils.StringUtils.*
import static extension cn.edu.nuaa.aadl2.generatorC.utils.PropertyParser.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.ThreadTemplate.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.AnnexTemplate.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.ModeTemplate.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.FeatureTemplate.*;
import static extension cn.edu.nuaa.aadl2.generatorC.template.ConnectionTemplate.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.PropertyTemplate.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.Template.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.SubcomponentTemplate.*
import org.osate.aadl2.ProcessSubcomponent
import org.osate.aadl2.ProcessType
import org.osate.aadl2.ProcessImplementation
import cn.edu.nuaa.aadl2.generatorC.utils.Tools
import org.osate.aadl2.Subcomponent
import org.osate.aadl2.ThreadSubcomponent
import org.osate.aadl2.Element
import org.osate.aadl2.impl.DefaultAnnexSubclauseImpl
import org.osate.aadl2.impl.AnnexSubclauseImpl

import org.osate.aadl2.DataClassifier
import org.osate.aadl2.AnnexSubclause
import org.osate.ba.aadlba.impl.BehaviorAnnexImpl
import org.osate.aadl2.DefaultAnnexSubclause
import java.util.List
import org.osate.aadl2.Mode
import org.osate.aadl2.Connection
import org.osate.aadl2.DataSubcomponent
import cn.edu.nuaa.aadl2.generatorC.utils.FileHelper

class ProcessTemplate {

//	public static String init = '''
//		int time_cycle;//
//		int time_current;//
//		int ticks_pass;//
//	'''
//	public static String time_current = "time_current"
//	public static String time_cycle = "time_cycle"
	public static String init = ""
	public static String time_current = ""
	public static String time_cycle = ""
	public static String process_folder = ""

	/*
	 * 处理系统实现下的进程子组件
	 * @param parentFolder 系统实现目录路径
	 * @param processSubcomponent 进程子组件
	 * @param systemName 系统名称
	 */
	def static genSystemProcessSubcomponent(String parentFolder, ProcessSubcomponent processSubcomponent,
		String systemName) {
		Tools.folder(parentFolder + "/process_" + processSubcomponent.name.convert)
		Tools.createFile(parentFolder + "/process_" + processSubcomponent.name.convert,
			systemName.convert + "-" + processSubcomponent.name.convert + ".c",
			processSubcomponent.template(systemName).toString)
	}

	def static create(ProcessSubcomponent subcomponent, String systemFolder) '''
		«IF meta_systemfolder.equals(Tools.ifolder.name)»
			«process_folder=systemFolder+"/"+subcomponent.classifier.name.toLowerCase.replace(".","_")»
		«ELSE»
			«process_folder=systemFolder+"/"+subcomponent.classifier.name.toLowerCase.replace(".","_")»
		«ENDIF»
		«Tools.createFile(process_folder,subcomponent.classifier.name.toLowerCase.replace(".","_")+"_process.c",subcomponent.template("").toString)»
		«Tools.createFile(process_folder,subcomponent.classifier.name.toLowerCase.replace(".","_")+"_process.h",subcomponent.head.toString)»		
		
		«Tools.addContent(systemFolder,Template.systemheadfile,"#include \""+subcomponent.classifier.name.toLowerCase.replace(".","_")+"_process.h"+"\"")»
		«process_folder=""»
	'''

	def static head(ProcessSubcomponent subcomponent) {
		var process = subcomponent.classifier
		switch process {
			ProcessType: '''
				/*process type*/
				«Template.head»								
				int «process.name.convert»_init();
				int timer_schedule();
				int «process.name.convert»_init_task();
«««				«FOR property : process.allPropertyAssociations»
«««					«property.template»
«««				«ENDFOR»			
				
			'''
			ProcessImplementation: '''
				/*process implementation*/
				«Template.head»
				#include "«Template.systemheadfile»"
				/***********************************
				* deal with process feature!!!!	start!
				************************************/	
				«FOR feature : process.allFeatures»
					«feature.template»
				«ENDFOR»				
				/***********************************
				* deal with process feature!!!!	end!
				************************************/
				
				/***********************************
				* deal with process subcomponent!!!!	start!
				************************************/				
				«IF process.allSubcomponents!=null»
					«FOR Subcomponent sub : process.allSubcomponents»
						«switch sub{
							ThreadSubcomponent : '''
								void «sub.classifier.name.convert»();  
							'''
							DataSubcomponent :'''
								«sub.template(process_folder)»
							'''
							default: '''
								deafult at processtemplate line 116 with class: «sub.class»
							'''
						}»
					«ENDFOR»
				«ENDIF»	
				/***********************************
				* deal with process subcomponent!!!!	end!
				************************************/				
				
				«««				/**************************
«««				* deal with connection start
«««				**************************/		
«««				«process.allConnections.dealWithConnections»
«««				/**************************
«««				* deal with connection end
«««				**************************/			
				
				
				void process_«process.name.convert»();
			'''
		}
	}

	def static template(ProcessSubcomponent subcomponent, String systemname) {
		var process = subcomponent.classifier
		var children = process.children
		switch process {
			ProcessType: '''
				«process.allFeatures.toString»
				/*process type*/
				«Template.head»
			'''
			ProcessImplementation: '''
				
				/*process implementation*/
				«Template.head»
				#include "«subcomponent.classifier.name.toLowerCase.replace(".","_")+"_process.h"»"
				#define STACK_SIZE 1000  
				int process_«process.name.convert»()
				{
				«IF process.allSubcomponents!==null»
					«FOR Subcomponent sub : process.allSubcomponents»
						«switch sub{
								ThreadSubcomponent : '''
«««									«Tools.addContent(Template.systemheadfile,"int "+sub.classifier.name.convert+"_time;")»
									
									«sub.createThread(process_folder)»
								'''
								default:'''
								   processTemplate 150	default =======«sub.category.getName()»===========
								'''
							}»
					«ENDFOR»
				«ENDIF»	
				«««				«IF process.isVxWorks»
«««					«process.name.convert»_init_VxWorks();
«««					«process.name.convert»_init_VxWorks_task();	
«««				«ELSE»
					«process.name.convert»_init();
					«process.name.convert»_init_task();					
				«««				«ENDIF»
«««				«IF process.type.getAllFeatures!=null»						
«««				«ENDIF»
«««				«IF subcomponent.processor!=null»
«««					«IF subcomponent.processor.schedule!=null»
«««						«IF subcomponent.processor.schedule.equalsIgnoreCase("FixedTimeLine")»
«««							/*FixedTimeLine*/
«««							
«««							timer_schedule();															
«««						«ENDIF»
«««						«IF subcomponent.processor.schedule.equalsIgnoreCase("Round_Robin_Protocol")»
«««							/*Round_Robin_Protocol*/
«««							
«««						«ENDIF»
«««						«IF subcomponent.processor.schedule.equalsIgnoreCase("RMS")»
«««							/*RMS*/
«««							
«««						«ENDIF»
«««						«IF subcomponent.processor.schedule.equalsIgnoreCase("Round_Robin_Protocol")»
«««							/*EDF*/
«««						«ENDIF»
«««					«ENDIF»
«««				«ENDIF»
				«IF process.ownedAnnexSubclauses.size == 0»
					«process.name.convertNo2Low»_BehaviorAnnex();
				«ENDIF»
				}
				
				/*init task*/
				int «process.name.convert»_init_task()
				{
				«««					«IF process.allSubcomponents!=null»
«««					«process.allFeatures.toString»
«««					«ENDIF»
					«FOR Subcomponent sub : process.allSubcomponents»
					«switch sub{
						ThreadSubcomponent : '''
							if ( taskSpawn("«sub.classifier.name.convert»",«sub.priority»,0,STACK_SIZE, (FUNCPTR)«sub.classifier.name.convert»,1,2,3,4,5,6,7,8,9,10) == ERROR)
							{
								printf("ERR:Memory Not Enough!\n");	
								taskDelay(0);	
							}
						'''
						default:'''
							processTemplate 167	default =======«sub.category.getName()»===========
						'''
					}»
				«ENDFOR»
				/*任务创建完之后挂起任务*/
				taskDelay(0);	
				}
				
				/*init process*/
				int «process.name.convert»_init()
				{
					//TO-DO
				«««					«Tools.addContent(Template.systemheadfile,init)»
«««					time_current=-1;
«««					ticks_pass=0;
«««					time_cycle=«process.period»;
«««					«IF process.allSubcomponents!=null»
«««						«FOR Subcomponent sub : process.allSubcomponents»
«««							«switch sub{
«««								ThreadSubcomponent : '''
«««									«Tools.addContent(Template.systemheadfile,"int "+sub.classifier.name.convert+"_time;")»
«««									«Tools.addContent(Template.systemheadfile,"short "+sub.classifier.name.convert+"_finish;")»
«««									«Tools.addContent(Template.systemheadfile,"int "+sub.classifier.name.convert+"_failure_count;")»
«««									«Tools.addContent(Template.systemheadfile,"int "+sub.classifier.name.convert+"_begin;")»
«««									«Tools.addContent(Template.systemheadfile,"int "+sub.classifier.name.convert+"_end;")»
«««									«sub.classifier.name.convert+"_time"»=«sub.period»;
«««									«sub.classifier.name.convert+"_finish"»=1;
«««									«sub.classifier.name.convert+"_failure_count"»=1;
«««									«IF sub.time_Window!=null»
«««										«sub.classifier.name.convert+"_begin"»=«sub.time_Window.get(0)»;
«««										«sub.classifier.name.convert+"_end"»=«sub.time_Window.get(1)»;
«««									«ENDIF»
«««								'''
«««							}»
«««						«ENDFOR»
«««					«ENDIF»		}
«««					/*for fixedtimeline*/
«««					int timer_schedule()
«««					{
«««						time_current++;
«««						time_current=(time_current+time_cycle)%time_cycle;
«««					}
«««				-----------------------------------------------------------------------------
«««					«IF process.ownedModes.size >0»
«««						«dealProcessMode(process.ownedModes,process.allSubcomponents)»
«««					«ELSE»
«««						«dealTaskCall(process.allSubcomponents,process.ownedConnections)»
«««					«ENDIF»	
«««				-----------------------------------------------------------------------------	
«««					
«««					
«««					
									}

				«IF process.ownedAnnexSubclauses.size == 0»
					«FOR  annexSubclause : process.ownedAnnexSubclauses»
						«AnnexSwitch(process.name.convertNo2Low,annexSubclause as DefaultAnnexSubclauseImpl,"",false).toString»
					«ENDFOR»
				«ENDIF»		
				
				«««				/* MODE if had */
«««				«IF process.ownedModes.size > 0»
«««					«process.ownedModes.genMode.toString.clearspace»
«««					current_mode : Modes;
«««				«ENDIF»					
«««				
«««				«IF process.ownedModes.size > 0»
«««					«process.ownedModes.initMode.toString.clearspace»
«««				«ENDIF»
«««				
«««				«IF process.ownedModeTransitions.size > 0»
«««					«process.ownedModeTransitions.genModeTransition»
«««				«ENDIF»
				
				
			'''
		}
	}

/*
 * 根据进程所处的不同模式调用该模式下的子组件
 * @param modes 进程拥有的模式列表
 * @param subcomponents 进程的子组件列表
 */
//	def static dealProcessMode(List<Mode> modes, List<Subcomponent> subcomponents) '''
//		switch current_mode{
//		«FOR mode : modes»
//			case «mode.name»:
//				«FOR subcomponent : subcomponents»
//					«switch subcomponent{
//						ThreadSubcomponent:'''
//							«IF subcomponent.inModes.contains(mode)»
//								«subcomponent.name»_task.Start();
//							«ENDIF»
//						'''
//					}»
//				«ENDFOR»
//			break;
//		«ENDFOR»
//		};
//	'''
//	/*
//	 * 当进程没有模式变换时调用进程下的子组件
//	 * @param subcomponents 进程的子组件列表
//	 * @param connections 进程的连接列表
//	 */
//	def static dealTaskCall(List<Subcomponent> subcomponents, List<Connection> connections) '''
//		«FOR subcomponent : subcomponents»
//			«switch subcomponent{
//					ThreadSubcomponent:'''
//						«IF subcomponent.allFeatures.size>0»
//							«subcomponent.name.convertNo2Low»_task.Start(«genConParam(connections,subcomponent).toString.clearspace.formatParam»);
//						«ENDIF»
//					'''
//				}»
//		«ENDFOR»
//	'''
//	def static init(ProcessImplementation process) '''
//		«Tools.addContent(process.name.convert+".h","int "+process.name.convert+"_cycle"+";")»
//		«Tools.addContent(process.name.convert+".h","int "+process.name.convert+"_current"+";")»
//	'''
}
